/*
	This file is part of Vajolet.

    Vajolet is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Vajolet is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Vajolet.  If not, see <http://www.gnu.org/licenses/>
*/

//----------------------------------------------------------------------------------
//	INCLUDE
//-----------------------------------------------------------------------------------
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include "vajolet.h"
#include "board.h"
#include "timer.h"
#include "movegen.h"
#include "move.h"
#include "search.h"
#include "eval.h"

//----------------------------------------------------------------------------------
//	CODE
//----------------------------------------------------------------------------------
int pipe;
HANDLE hstdin;



int comInit() {

	unsigned long dw;
	hstdin = GetStdHandle(STD_INPUT_HANDLE);
	pipe = !GetConsoleMode(hstdin, &dw);

	if (!pipe) {
		SetConsoleMode(hstdin,dw&~(ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT));
		FlushConsoleInputBuffer(hstdin);
	} else {
		setvbuf(stdin,NULL,_IONBF,0);
		setvbuf(stdout,NULL,_IONBF,0);
	}
	
	return 0;

}

int input() {
	unsigned long dw=0;

	if (stdin->_cnt > 0 )
	{
		return 1;
	}

	if (pipe) {
		if (!PeekNamedPipe(hstdin, 0, 0, 0, &dw, 0)) return 1;
		return dw;
	} else {
		GetNumberOfConsoleInputEvents(hstdin, &dw);
		if (dw >= 1) return 1;
	}

	return 0;
}



void command(void){
	char command[16384];
	/*if(!input()){
		return;
	}*/
	fgets( command, sizeof(command), stdin );
	
	for (;;)
    {
        size_t sz = strlen(command);
        if ( sz > 0 && command[sz-1] < 32 )
        {
            command[sz-1] = 0;
        }
        else break;
    }
	std::string cmd( command );		
	if ( cmd.empty() ){
		return;
	}
	if ( cmd == "quit" )
	{
		exit(0);
	}
	if ( cmd == "isready" )
	{
		printf("readyok\n");
		return;

	}
	if ( cmd == "uci" )
	{
		std::cout<<"id name "<<PROGRAM_NAME<<" "<<VERSION<<std::endl;
		std::cout<<"id author Marco Belli"<<std::endl;
		std::cout<<"option name Hash type spin default 1 min 1 max 512"<<std::endl;
        std::cout<<"uciok"<<std::endl;
		
		return;

    }
	if ( cmd == "ucinewgame" )
	{
		board.init();
		Search::clearHistoryTable();
		for(int i=0;i<2;i++){
			for(int n=0;n<200;n++){
				Search::killermoves[i][n][0].packed=0;
				Search::killermoves[i][n][1].packed=0;
			}
		}
		board.transTT.setSize(board.transTT.MBsize);
		
			
		return;
    }
	if( cmd=="d"){
		board.display();
		return;
	}
	if( cmd=="eval"){
		board.eval<true>();
		return;
	}
	if( cmd=="stop"){
		return;
	}

	std::vector< std::string > tokens;
	char buf[4096];
	strcpy( buf, cmd.c_str() );
	char *tok = strtok( buf, " \t\r\n\v" );
	if(tok==NULL){
		return; 
	}
	do
	{
		tokens.push_back( tok );
	} while ( (tok = strtok( 0, " \t\r\n\v" )) );
	if ( tokens.empty() )
		return;
	if( tokens[0] == "setoption"){
		if(tokens[2]=="Hash"){
			board.transTT.setSize(atoi(tokens[4].c_str()));
		}
	}
	if( tokens[0] == "setvalue"){
		if(tokens[1]=="queenValue"){
			Board::PIECESCORE[Board::whiteQueens]=atoi(tokens[2].c_str());
			Board::PIECESCORE[Board::blackQueens]=-atoi(tokens[2].c_str());
		}
		if(tokens[1]=="rookValue"){
			Board::PIECESCORE[Board::whiteRooks]=atoi(tokens[2].c_str());
			Board::PIECESCORE[Board::blackRooks]=-atoi(tokens[2].c_str());
		}
		if(tokens[1]=="bishopValue"){
			Board::PIECESCORE[Board::whiteBishops]=atoi(tokens[2].c_str());
			Board::PIECESCORE[Board::blackBishops]=-atoi(tokens[2].c_str());
		}
		if(tokens[1]=="knightValue"){
			Board::PIECESCORE[Board::whiteKnights]=atoi(tokens[2].c_str());
			Board::PIECESCORE[Board::blackKnights]=-atoi(tokens[2].c_str());
		}
		/*if(tokens[1]=="bishopPairBonusOpening"){
			bishopPairBonusOpening=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="bishopPairBonusEndgame"){
			bishopPairBonusEndgame=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="bishopPairBonus2Opening"){
			bishopPairBonus2Opening=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="bishopPairBonus2Endgame"){
			bishopPairBonus2Endgame=atoi(tokens[2].c_str());
		}*/
		if(tokens[1]=="bishopRedundancyPenaltyOpening"){
			bishopRedundancyPenaltyOpening=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="bishopRedundancyPenaltyEndgame"){
			bishopRedundancyPenaltyEndgame=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="rookRedundancy1Opening"){
			rookRedundancy1Opening=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="rookRedundancy1Endgame"){
			rookRedundancy1Endgame=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="rookRedundancy2Opening"){
			rookRedundancy2Opening=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="rookRedundancy2Endgame"){
			rookRedundancy2Endgame=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="knightRedundancyOpening"){
			knightRedundancyOpening=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="knightRedundancyEndgame"){
			knightRedundancyEndgame=atoi(tokens[2].c_str());
		}

		if(tokens[1]=="isolatedPawnPenaltyEndgame00"){
			isolatedPawnPenaltyEndgame[0][0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame01"){
			isolatedPawnPenaltyEndgame[0][1]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame02"){
			isolatedPawnPenaltyEndgame[0][2]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame03"){
			isolatedPawnPenaltyEndgame[0][3]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame04"){
			isolatedPawnPenaltyEndgame[0][4]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame05"){
			isolatedPawnPenaltyEndgame[0][5]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame06"){
			isolatedPawnPenaltyEndgame[0][6]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame07"){
			isolatedPawnPenaltyEndgame[0][7]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame10"){
			isolatedPawnPenaltyEndgame[1][0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame11"){
			isolatedPawnPenaltyEndgame[1][1]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame12"){
			isolatedPawnPenaltyEndgame[1][2]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame13"){
			isolatedPawnPenaltyEndgame[1][3]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame14"){
			isolatedPawnPenaltyEndgame[1][4]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame15"){
			isolatedPawnPenaltyEndgame[1][5]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame16"){
			isolatedPawnPenaltyEndgame[1][6]=atoi(tokens[2].c_str());
		}if(tokens[1]=="isolatedPawnPenaltyEndgame17"){
			isolatedPawnPenaltyEndgame[1][7]=atoi(tokens[2].c_str());
		}

	
		if(tokens[1]=="doubledPawnPenaltyOpening1"){
			doubledPawnPenaltyOpening[0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="doubledPawnPenaltyOpening2"){
			doubledPawnPenaltyOpening[1]=atoi(tokens[2].c_str());
		}if(tokens[1]=="doubledPawnPenaltyEndgame1"){
			doubledPawnPenaltyEndgame[0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="doubledPawnPenaltyEndgame2"){
			doubledPawnPenaltyEndgame[1]=atoi(tokens[2].c_str());
		}
		
		
		if(tokens[1]=="chainedPawnBonusOpening0"){
			chainedPawnBonusOpening[0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusOpening1"){
			chainedPawnBonusOpening[1]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusOpening2"){
			chainedPawnBonusOpening[2]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusOpening3"){
			chainedPawnBonusOpening[3]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusOpening4"){
			chainedPawnBonusOpening[4]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusOpening5"){
			chainedPawnBonusOpening[5]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusOpening6"){
			chainedPawnBonusOpening[6]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusOpening7"){
			chainedPawnBonusOpening[7]=atoi(tokens[2].c_str());
		}
		
		if(tokens[1]=="chainedPawnBonusEndgame0"){
			chainedPawnBonusEndgame[0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusEndgame1"){
			chainedPawnBonusEndgame[1]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusEndgame2"){
			chainedPawnBonusEndgame[2]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusEndgame3"){
			chainedPawnBonusEndgame[3]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusEndgame4"){
			chainedPawnBonusEndgame[4]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusEndgame5"){
			chainedPawnBonusEndgame[5]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusEndgame6"){
			chainedPawnBonusEndgame[6]=atoi(tokens[2].c_str());
		}if(tokens[1]=="chainedPawnBonusEndgame7"){
			chainedPawnBonusEndgame[7]=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="passedPawnBonusOpening"){
			passedPawnBonusOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="passedPawnBonusEndgame"){
			passedPawnBonusEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="candidateBonusOpening"){
			candidateBonusOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="candidateBonusEndgame"){
			candidateBonusEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="backwardPawnPenaltyOpening0"){
			backwardPawnPenaltyOpening[0]=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="backwardPawnPenaltyOpening1"){
			backwardPawnPenaltyOpening[1]=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="backwardPawnPenaltyOpening2"){
			backwardPawnPenaltyOpening[2]=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="backwardPawnPenaltyOpening3"){
			backwardPawnPenaltyOpening[3]=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="backwardPawnPenaltyOpening4"){
			backwardPawnPenaltyOpening[4]=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="backwardPawnPenaltyOpening5"){
			backwardPawnPenaltyOpening[5]=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="backwardPawnPenaltyOpening6"){
			backwardPawnPenaltyOpening[6]=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="backwardPawnPenaltyOpening7"){
			backwardPawnPenaltyOpening[7]=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="backwardPawnPenaltyEndgame0"){
			backwardPawnPenaltyEndgame[0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="backwardPawnPenaltyEndgame1"){
			backwardPawnPenaltyEndgame[1]=atoi(tokens[2].c_str());
		}if(tokens[1]=="backwardPawnPenaltyEndgame2"){
			backwardPawnPenaltyEndgame[2]=atoi(tokens[2].c_str());
		}if(tokens[1]=="backwardPawnPenaltyEndgame3"){
			backwardPawnPenaltyEndgame[3]=atoi(tokens[2].c_str());
		}if(tokens[1]=="backwardPawnPenaltyEndgame4"){
			backwardPawnPenaltyEndgame[4]=atoi(tokens[2].c_str());
		}if(tokens[1]=="backwardPawnPenaltyEndgame5"){
			backwardPawnPenaltyEndgame[5]=atoi(tokens[2].c_str());
		}if(tokens[1]=="backwardPawnPenaltyEndgame6"){
			backwardPawnPenaltyEndgame[6]=atoi(tokens[2].c_str());
		}if(tokens[1]=="backwardPawnPenaltyEndgame7"){
			backwardPawnPenaltyEndgame[7]=atoi(tokens[2].c_str());
		}if(tokens[1]=="spaceWeight"){
			spaceWeight=atoi(tokens[2].c_str());
		}if(tokens[1]=="passedPawnPenaltyFileAH"){
			passedPawnPenaltyFileAH=atoi(tokens[2].c_str());
		}if(tokens[1]=="passedPawnSupportedBonus"){
			passedPawnSupportedBonus=atoi(tokens[2].c_str());
		}if(tokens[1]=="passedPawnNonBlockedBonus"){
			passedPawnNonBlockedBonus=atoi(tokens[2].c_str());
		}if(tokens[1]=="knightOutpostBonus"){
			knightOutpostBonus=atoi(tokens[2].c_str());
		}if(tokens[1]=="bishopOutpostBonus"){
			bishopOutpostBonus=atoi(tokens[2].c_str());
		}/*if(tokens[1]=="bishopThreathOpening"){
			bishopThreathOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="bishopThreathEndgame"){
			bishopThreathEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="knightThreathOpening"){
			knightThreathOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="knightThreathEndgame"){
			knightThreathEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookThreathOpening"){
			rookThreathOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookThreathEndgame"){
			rookThreathEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="queenThreathOpening"){
			queenThreathOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="queenThreathEndgame"){
			queenThreathEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="bishopUndefendedOpening"){
			bishopUndefendedOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="bishopUndefendedEndgame"){
			bishopUndefendedEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="knightUndefendedOpening"){
			knightUndefendedOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="knightUndefendedEndgame"){
			knightUndefendedEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookUndefendedOpening"){
			rookUndefendedOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookUndefendedEndgame"){
			rookUndefendedEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="queenUndefendedOpening"){
			queenUndefendedOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="queenUndefendedEndgame"){
			queenUndefendedEndgame=atoi(tokens[2].c_str());
		}*/
		if(tokens[1]=="undefendedMinorPenaltyOpening"){
			undefendedMinorPenalty=makeScore(atoi(tokens[2].c_str()),eg_value(undefendedMinorPenalty));
		}if(tokens[1]=="undefendedMinorPenaltyEndgame"){
			undefendedMinorPenalty=makeScore(mg_value(undefendedMinorPenalty),atoi(tokens[2].c_str()));
		}
		if(tokens[1]=="threatPenaltyOpeningQ"){
			threatPenalty[Board::whiteQueens]=makeScore(atoi(tokens[2].c_str()),eg_value(threatPenalty[Board::whiteQueens]));
		}if(tokens[1]=="threatPenaltyOpeningR"){
			threatPenalty[Board::whiteRooks]=makeScore(atoi(tokens[2].c_str()),eg_value(threatPenalty[Board::whiteRooks]));
		}if(tokens[1]=="threatPenaltyOpeningB"){
			threatPenalty[Board::whiteBishops]=makeScore(atoi(tokens[2].c_str()),eg_value(threatPenalty[Board::whiteBishops]));
		}if(tokens[1]=="threatPenaltyOpeningN"){
			threatPenalty[Board::whiteKnights]=makeScore(atoi(tokens[2].c_str()),eg_value(threatPenalty[Board::whiteKnights]));
		}
		if(tokens[1]=="threatPenaltyEndgameQ"){
			threatPenalty[Board::whiteQueens]=makeScore(mg_value(threatPenalty[Board::whiteQueens]),atoi(tokens[2].c_str()));
		}if(tokens[1]=="threatPenaltyEndgameR"){
			threatPenalty[Board::whiteRooks]=makeScore(mg_value(threatPenalty[Board::whiteRooks]),atoi(tokens[2].c_str()));
		}if(tokens[1]=="threatPenaltyEndgameB"){
			threatPenalty[Board::whiteBishops]=makeScore(mg_value(threatPenalty[Board::whiteBishops]),atoi(tokens[2].c_str()));
		}if(tokens[1]=="threatPenaltyEndgameN"){
			threatPenalty[Board::whiteKnights]=makeScore(mg_value(threatPenalty[Board::whiteKnights]),atoi(tokens[2].c_str()));
		}


		if(tokens[1]=="knightMobOpA"){
			knightMobOpA=atoi(tokens[2].c_str())/256.0;
		}if(tokens[1]=="knightMobOpM"){
			knightMobOpM=atoi(tokens[2].c_str())/100.0;
		}if(tokens[1]=="knightMobOpQ"){
			knightMobOpQ=atoi(tokens[2].c_str());
		}if(tokens[1]=="knightMobOp0"){
			knightMobOp0=atoi(tokens[2].c_str());
		}if(tokens[1]=="knightMobEnA"){
			knightMobEnA=atoi(tokens[2].c_str())/256.0;
		}if(tokens[1]=="knightMobEnM"){
			knightMobEnM=atoi(tokens[2].c_str())/100.0;
		}if(tokens[1]=="knightMobEnQ"){
			knightMobEnQ=atoi(tokens[2].c_str());
		}if(tokens[1]=="knightMobEn0"){
			knightMobEn0=atoi(tokens[2].c_str());
		}if(tokens[1]=="bishopMobOpA"){
			bishopMobOpA=atoi(tokens[2].c_str())/256.0;
		}if(tokens[1]=="bishopMobOpM"){
			bishopMobOpM=atoi(tokens[2].c_str())/100.0;
		}if(tokens[1]=="bishopMobOpQ"){
			bishopMobOpQ=atoi(tokens[2].c_str());
		}if(tokens[1]=="bishopMobOp0"){
			bishopMobOp0=atoi(tokens[2].c_str());
		}if(tokens[1]=="bishopMobEnA"){
			bishopMobEnA=atoi(tokens[2].c_str())/256.0;
		}if(tokens[1]=="bishopMobEnM"){
			bishopMobEnM=atoi(tokens[2].c_str())/100.0;
		}if(tokens[1]=="bishopMobEnQ"){
			bishopMobEnQ=atoi(tokens[2].c_str());
		}if(tokens[1]=="bishopMobEn0"){
			bishopMobEn0=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookMobOpA"){
			rookMobOpA=atoi(tokens[2].c_str())/256.0;
		}if(tokens[1]=="rookMobOpM"){
			rookMobOpM=atoi(tokens[2].c_str())/100.0;
		}if(tokens[1]=="rookMobOpQ"){
			rookMobOpQ=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookMobOp0"){
			rookMobOp0=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookMobEnA"){
			rookMobEnA=atoi(tokens[2].c_str())/256.0;
		}if(tokens[1]=="rookMobEnM"){
			rookMobEnM=atoi(tokens[2].c_str())/100.0;
		}if(tokens[1]=="rookMobEnQ"){
			rookMobEnQ=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookMobEn0"){
			rookMobEn0=atoi(tokens[2].c_str());
		}if(tokens[1]=="queenMobOpA"){
			queenMobOpA=(float)atoi(tokens[2].c_str())/256.0;
		}if(tokens[1]=="queenMobOpM"){
			queenMobOpM=(float)atoi(tokens[2].c_str())/100.0;
		}if(tokens[1]=="queenMobOpQ"){
			queenMobOpQ=(float)atoi(tokens[2].c_str());
		}if(tokens[1]=="queenMobOp0"){
			queenMobOp0=(float)atoi(tokens[2].c_str());
		}if(tokens[1]=="queenMobEnA"){
			queenMobEnA=(float)atoi(tokens[2].c_str())/256.0;
		}if(tokens[1]=="queenMobEnM"){
			queenMobEnM=(float)atoi(tokens[2].c_str())/100.0;
		}if(tokens[1]=="queenMobEnQ"){
			queenMobEnQ=(float)atoi(tokens[2].c_str());
		}if(tokens[1]=="queenMobEn0"){
			queenMobEn0=(float)atoi(tokens[2].c_str());
		}if(tokens[1]=="KingNearOwnPassedPawnBonus"){
			KingNearOwnPassedPawnBonus=atoi(tokens[2].c_str());
		}if(tokens[1]=="KingNearEnemyPassedPawnBonus"){
			KingNearEnemyPassedPawnBonus=atoi(tokens[2].c_str());
		}if(tokens[1]=="kingShieldBonus0"){
			kingShieldBonus[0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="kingShieldBonus1"){
			kingShieldBonus[1]=atoi(tokens[2].c_str());
		}if(tokens[1]=="kingShieldBonus2"){
			kingShieldBonus[2]=atoi(tokens[2].c_str());
		}if(tokens[1]=="kingShieldBonus3"){
			kingShieldBonus[3]=atoi(tokens[2].c_str());
		}if(tokens[1]=="kingSafety0"){
			kingSafety0=atoi(tokens[2].c_str());
		}if(tokens[1]=="kingSafety1"){
			kingSafety1=atoi(tokens[2].c_str());
		}if(tokens[1]=="kingSafety2"){
			kingSafety2=atoi(tokens[2].c_str());
		}if(tokens[1]=="futility0"){
			futility[0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="futility1"){
			futility[1]=atoi(tokens[2].c_str());
		}if(tokens[1]=="futility2"){
			futility[2]=atoi(tokens[2].c_str());
		}if(tokens[1]=="futility3"){
			futility[3]=atoi(tokens[2].c_str());
		}if(tokens[1]=="futility4"){
			futility[4]=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="razorMargin"){
			razorMargin[0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="IIDMargin"){
			IIDmargin=atoi(tokens[2].c_str());
		}if(tokens[1]=="IIDdepth0"){
			IIDdepth[0]=atoi(tokens[2].c_str());
		}if(tokens[1]=="IIDdepth1"){
			IIDdepth[1]=atoi(tokens[2].c_str());
		}if(tokens[1]=="IIDdepth2"){
			IIDdepth[2]=atoi(tokens[2].c_str());
		}if(tokens[1]=="futilityMargin1"){
			futilityMargin[1]=atoi(tokens[2].c_str());
		}if(tokens[1]=="futilityMargin2"){
			futilityMargin[2]=atoi(tokens[2].c_str());
		}if(tokens[1]=="futilityMargin3"){
			futilityMargin[3]=atoi(tokens[2].c_str());
		}if(tokens[1]=="futilityMargin4"){
			futilityMargin[4]=atoi(tokens[2].c_str());
		}if(tokens[1]=="futilityMargin5"){
			futilityMargin[5]=atoi(tokens[2].c_str());
		}if(tokens[1]=="futilityMargin6"){
			futilityMargin[6]=atoi(tokens[2].c_str());
		}if(tokens[1]=="threatGain"){
			threatGain=atoi(tokens[2].c_str());
		}
		
/*		if(tokens[1]=="rookOn7Opening"){
			rookOn7Opening=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookOn7Endgame"){
			rookOn7Endgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="queenOn7Opening"){
			queenOn7Opening=atoi(tokens[2].c_str());
		}if(tokens[1]=="queenOn7Endgame"){
			queenOn7Endgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookOnPawnOpening"){
			rookOnPawnOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookOnPawnEndgame"){
			rookOnPawnEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="queenOnPawnOpening"){
			queenOnPawnOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="queenOnPawnEndgame"){
			queenOnPawnEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookOnOpenOpening"){
			rookOnOpenOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookOnOpenPawnEndgame"){
			rookOnOpenPawnEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookOnSemiOpening"){
			rookOnSemiOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="rookOnSemiPawnEndgame"){
			rookOnSemiPawnEndgame=atoi(tokens[2].c_str());
		}*/if(tokens[1]=="badBishopOpening"){
			badBishopOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="badBishopEndgame"){
			badBishopEndgame=atoi(tokens[2].c_str());
		}if(tokens[1]=="littleCenterControlOpening"){
			littleCenterControlOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="bigCenterControlOpening"){
			bigCenterControlOpening=atoi(tokens[2].c_str());
		}if(tokens[1]=="pawnEndgameBonusPst"){
			pawnEndgameBonusPst=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="siblingValue"){
			siblingValue=atoi(tokens[2].c_str());
		}
		if(tokens[1]=="PVredQ"){
			PVredQ=atof(tokens[2].c_str());
			Search::initReduction();
		}
		if(tokens[1]=="PVredM"){
			PVredM=atof(tokens[2].c_str());
			Search::initReduction();
		}
		if(tokens[1]=="nonPVRedQ"){
			nonPVRedQ=atof(tokens[2].c_str());
			Search::initReduction();
		}
		if(tokens[1]=="nonPVRedM"){
			nonPVRedM=atof(tokens[2].c_str());
			Search::initReduction();
		}
		

		
		board.initPST();
		board.init();
		



	}
	if ( tokens[0] == "perft" )
	{
		if ( tokens.size() > 1 )
		{
			long d = strtol( tokens[1].c_str(), 0, 10 );
			Timer tim;

			tim.reset();
			tim.init();
			unsigned long long  tot=perft(d);
			tim.stop();
			std::cout<<"perft result: "<<tot<<" moves, "<<tim.getms()<<" ms\n";
			std::cout<<"speed: "<<(float)tot/tim.getms()<<" Knps\n";
		}
	}
	else if ( tokens[0] == "divide" )
	{
		if ( tokens.size() > 1 )
		{
			long d = strtol( tokens[1].c_str(), 0, 10 );
			Timer tim;

			tim.reset();
			tim.init();
			unsigned long long  tot=divide(d);
			tim.stop();
			std::cout<<"perft result: "<<tot<<" moves, "<<tim.getms()<<" ms\n";
			std::cout<<"speed: "<<(float)tot/tim.getms()<<" Knps\n";
		}
	}
	else if ( tokens[0] =="info" ){
		std::cout << PROGRAM_NAME << std::endl;
		std::cout << "revision: "<< VERSION <<std::endl;
		std::cout <<"build date: " << __DATE__ <<" "<<__TIME__<<std::endl;
		std::cout <<"moveGenerator Version: "<< MOVEGEN_VERSION <<std::endl;
	}
	if ( tokens[0] == "go" )
	{
		//board.display();
			
		Search src;
		src.setSearchtime(0);
		src.uciMovesTogo=40;
		src.maxTime=0;
		src.infiniteSearch=true;
		src.expired=false;
		src.maxDepth=50;
		for (unsigned int i=1; i<tokens.size(); i++)
		{
			/*if ( tokens[i] == "ponder" )
			{
				ponder = 1;
			}
			else */if ( tokens[i] == "movestogo" )
			{
				if ( i+1 < tokens.size() )
				{
					src.uciMovesTogo = strtol( tokens[i+1].c_str(), 0, 10 );
						
					src.uciMovesTogo++; // mi tengo un po di tempo a disposizione
					if(src.uciMovesTogo<=0){
						src.uciMovesTogo=1;
					}
					i++;
				}
			}
			else if ( tokens[i] == "wtime" )
			{
				if ( i+1 < tokens.size() )
				{
					src.wtime = strtol( tokens[i+1].c_str(), 0, 10 );
					src.infiniteSearch=false;
					i++;
				}
			}
			else if ( tokens[i] == "btime" )
			{
				if ( i+1 < tokens.size() )
				{
					src.btime = strtol( tokens[i+1].c_str(), 0, 10 );
					src.infiniteSearch=false;
					i++;
				}
			}/*
			else if ( tokens[i] == "winc" )
			{
				if ( i+1 < tokens.size() )
				{
					winc = strtol( tokens[i+1].ansi(), 0, 10 );
					i++;
				}
			}
			else if ( tokens[i] == "binc" )
			{
				if ( i+1 < tokens.size() )
				{
					binc = strtol( tokens[i+1].ansi(), 0, 10 );
					i++;
				}
			}
			else if ( tokens[i] == "mate" )
			{
				if ( i+1 < tokens.size() )
				{
					sm.mateSearch = strtol( tokens[i+1].ansi(), 0, 10 );
					i++;
				}
			}
			else if ( tokens[i] == "nodes" )
			{
				if ( i+1 < tokens.size() )
				{
					sm.maxNodes = strtol( tokens[i+1].ansi(), 0, 10 );
					i++;
				}
			}*/
			else if ( tokens[i] == "depth" )
			{
				if ( i+1 < tokens.size() )
				{
					src.maxDepth = strtol( tokens[i+1].c_str(), 0, 10 );
					i++;
				}
			}
			else if ( tokens[i] == "infinite" )
			{
				src.infiniteSearch=true;
			}
			else if ( tokens[i] == "movetime" )
			{
				if ( i+1 < tokens.size() )
				{
					src.maxTime = strtol( tokens[i+1].c_str(), 0, 10 );
					src.infiniteSearch=false;
					src.wtime=-1;
					src.btime=-1;

					i++;
				}
			}/*
			else if ( tokens[i] == "searchmoves" )
			{
				movemode = 1;
			}
			else if ( movemode )
			{
				BitMove m[ bmaxMoves ];
				i32 vm = tt->bs.board.moves( m );
														
				i32 rturn = tt->bs.rturn;
				Move rm[ maxMoves ];
				i32 rvm = tt->bs.rboard.moves( rm, rturn );
				if ( vm != rvm )
				{
					logFmt("FATAL ERROR: new_movegen_bug!\n");
				}
														
				BitMove bm;
				bm.packed = 0;
				// parse_uci_move
				const char *mv = tokens[i].ansi();
				if ( tokens[i].length() >= 4 )
				{
					i32 fx = (*mv++ | 32) - 'a';
					i32 fy = '8' - (*mv++);
					i32 tx = (*mv++ | 32) - 'a';
					i32 ty = '8' - (*mv++);
					bm.from = (fy << 3) + fx;
					bm.to = (ty << 3) + tx;
					if ( *mv )
					{
						switch ( *mv | 32 )
						{
						case 'b':
							bm.promo = bishop;
							break;
						case 'n':
							bm.promo = knight;
							break;
						case 'r':
							bm.promo = rook;
							break;
						case 'q':
							bm.promo = queen;
							break;
						}
					}
					i32 i;
					for (i=0; i<vm; i++)
					{
						if ( bm.equal( m[i] ) )
						{
							break;
						}
					}
					if ( i < vm )
					{
						sm.searchMoves.push_back( m[i] );
					}
					else
					{
						char buf[32];
						bm.describeUCI( buf );
						logFmt("FATAL ERROR: invalid move passed by gui: %s\n", buf );
					}
				}
			}*/
				
		}
		if(src.maxTime==0){
			if(board.nextMove){
				src.setSearchtime(src.btime/src.uciMovesTogo);
			}else{
				src.setSearchtime(src.wtime/src.uciMovesTogo);
			}
		}else{
			src.setSearchtime(src.maxTime);
		}
		src.think();
	}
	else if ( tokens[0] == "position" )
	{
		unsigned int i;
		unsigned int movemode = 0;
		board.init();
		for (i=1; i<tokens.size(); i++)
		{
			if ( tokens[i] == "fen" )
			{
				unsigned int j;
				for (j=i+1; j<tokens.size(); j++)
				{
					if ( tokens[j] != "moves" && tokens[j] != "fen" && tokens[j] != "startpos" )
					{
					} else break;
				}
				if((j-i-1)==6){
					board.setupFen(tokens[i+1].c_str(),tokens[i+2].c_str(),tokens[i+3].c_str(),tokens[i+4].c_str(),strtol( tokens[i+5].c_str(), 0, 10 ),strtol( tokens[i+6].c_str(), 0, 10 ));
				}
				else if((j-i-1)==4){
					board.setupFen(tokens[i+1].c_str(),tokens[i+2].c_str(),tokens[i+3].c_str(),tokens[i+4].c_str(),0,0);
				}
				else{
				}
				//board.display();
					
				i = j-1;
			}
			else if ( tokens[i] == "startpos" )
			{
				board.init();
			}
			else if ( tokens[i] == "moves" )
			{
				movemode = 1;
			}
			else if ( movemode )
			{
				//std::cout<< "movemode ";
				Movegen mg(0);
				Move ttt;
				ttt.clear();
				//mg.genMoves();
				mg.killermoves[0]=0;
				mg.killermoves[1]=0;
				mg.setTTmove(ttt);

				Move m;
					
				// parse_uci_move
				const char *mv = tokens[i].c_str();
					
						

					
				if ( tokens[i].length() >= 4 )
				{
					unsigned int fx = (*mv++ | 32) - 'a';
					unsigned int fy = (*mv++)-'1';
					unsigned int tx = (*mv++ | 32) - 'a';
					unsigned int ty = (*mv++)-'1';
					m.from = (fy << 3) + fx;
					m.to = (ty << 3) + tx;
					if ( *mv )
					{
						switch ( *mv )
						{
						case 'b':
						case 'B':
							m.flags =Move::fpromotion;
							m.promotion= Move::promBishop;
							break;
						case 'n':
						case 'N':
							m.flags =Move::fpromotion;
							m.promotion= Move::promKnight;
							break;
						case 'r':
						case 'R':
							m.flags =Move::fpromotion;
							m.promotion= Move::promRook;
							break;
						case 'q':
						case 'Q':
							m.flags =Move::fpromotion;
							m.promotion= Move::promQueen;
							break;
						}
					}

					
					Move temp;
					Move t;
					bool found=false;
					while(mg.getNext(temp))
					{
						if ( m.from== temp.from &&  m.to== temp.to )
						{
							if(m.flags==Move::fpromotion){
								if(m.packed== temp.packed ){
									found=true;
									break;
								}
							}
							else{
								found=true;
								break;
							}
						}
					}
					if (found ==true && temp.packed!=0  && board.gameLineIndex<MAX_GAME_LENGTH)
					{
						board.makeMove(temp);
						//board.display();
					}
					else
					{
						board.display();
						std::cout<<"FATAL ERROR: invalid move passed by gui: "<<tokens[i].c_str()<<std::endl;
						getch();
					}
						
				}
				
			}
		}
		//std::cout<<"FEN: ";
		//board.displayFen();
	}

}


bool checkStopCommand(){
	char command[16384];
	if (!input()) return 0;
	
	gets( command);

	for (;;)
    {
        size_t sz = strlen(command);
        if ( sz > 0 && command[sz-1] < 32 )
        {
            command[sz-1] = 0;
        }
        else break;
    }
	std::string cmd( command );
	if ( cmd == "quit" )
	{
		exit(0);
	}
	if( cmd=="stop"){
		return true;
	}
	return false;
}
